#pragma once

#include <string>
#include <vector>
#include <iostream>
#include <unordered_map>
#include <sstream>
#include <fstream>

#include "log.hpp"
#include "Inet_Addr.hpp"

static const std::string http_line_sep = "\r\n";
static const std::string header_sep = ": ";
static const std::string request_line_sep = " ";
static const std::string status_line_sep = " ";
static const std::string web_root_directory = "wwwroot";
static const std::string web_index = "/index.html";

class Request
{
private:
    // 获取请求行详细信息
    void getRequestLineMassage()
    {
        std::stringstream ss(_request_line);
        ss >> _request_method >> _url >> _http_version;
    }

    // 获取请求报头每行的kv值
    bool getHeaderKV(const std::string &header, std::string &key, std::string &value)
    {
        int pos = header.find(header_sep);
        if (pos == std::string::npos || pos == 0) // 如果value为空或者key为空
            return false;

        key = header.substr(0, pos);
        value = header.substr(pos + header_sep.size());

        return true;
    }

    // 获取请求报头详细信息
    void getRequestHeadersMassage()
    {
        for (auto &header : _request_headers)
        {
            std::string key, value;
            if (getHeaderKV(header, key, value))
            {
                _header_kv.insert(std::make_pair(key, value));
            }
        }
    }
    // 获取访问资源的具体路径
    void getPath()
    {   
        if (_url == "/")
            _path += web_index;
        else    
            _path += _url;
    }

public:
    Request()
        : _block_line("\r\n"),
          _path(web_root_directory)
    {
    }

    std::string getPath(int)
    {
        return _path;
    }


    void Print()
    {
        // std::cout << _request_line << std::endl;
        // for (auto& header : _request_headers)
        // {
        //     std::cout << header << std::endl;
        // }
        // std::cout << _block_line << std::endl;
        // std::cout << _request_text << std::endl;

        std::cout << "###" << _request_method << request_line_sep << _path << request_line_sep << _http_version << http_line_sep;
        for (auto &header : _header_kv)
        {
            std::cout << "$$$" << header.first << header_sep << header.second << http_line_sep;
        }
        std::cout << _block_line;
        std::cout << _request_text;
    }

    // 反序列化
    void Deserialize(std::string &request_string)
    {
        // 获得请求行
        int pos = request_string.find(http_line_sep);
        _request_line = request_string.substr(0, pos);

        request_string.erase(0, pos + http_line_sep.size());

        // 获取请求报头
        while (true)
        {
            int pos = request_string.find(http_line_sep);
            std::string temp = request_string.substr(0, pos);    // 以'\r\n'为分隔符，获取请求报头的每一行
            request_string.erase(0, pos + http_line_sep.size()); // 读完一行，删一行

            // 如果获取的行的长度为0，说明读到空行，即请求报头读完，推出循环
            if (temp.size() == 0)
                break;

            _request_headers.push_back(temp); // 否则，就将读到的请求报头的一行插入报头数组
        }

        // 获取请求正文
        _request_text = request_string; // 正文就是剩下的请求

        getRequestLineMassage();
        getRequestHeadersMassage();
        getPath();
    }

private:
    /*-------------------请求的详细信息------------------*/
    // 请求行详细信息
    std::string _request_method; // 请求方法
    std::string _url;            // url
    std::string _http_version;   // http版本
    // 请求报头详细信息
    std::unordered_map<std::string, std::string> _header_kv; // 请求报头的K_V内容
    std::string _path;                                       // 访问的具体路径
    /*----------------------------------------------------*/

    /*----------------HTTP请求格式----------------------*/
    std::string _request_line;                 // 请求行
    std::vector<std::string> _request_headers; // 请求报头
    std::string _block_line;                   // 空行
    std::string _request_text;                 // 请求正文
    /*----------------------------------------------------*/
};

class Response
{
private:
    void getStatusLine()
    {
        _status_line = _http_version + status_line_sep +
                       std::to_string(_status_code) + status_line_sep +
                       _status_code_discribtion + http_line_sep;
    }

    void getResponseText()
    {
        std::ifstream in(_path, std::ios::binary);
        if (!in.is_open())
        {
            // std::cout << "open [" << _path << "] error" << std::endl;
            // exit(1);
            _response_text = "";
        }

        // 计算文件大小
        in.seekg(0, in.end);
        _content_length = in.tellg();
        in.seekg(0, in.beg);

        _response_text.resize(_content_length);

        in.read((char *)_response_text.c_str(), _content_length);
    }

    void getResponseHeader()
    {
        // _header_kv.insert(std::make_pair("Content-Length", std::to_string(_content_length)));
        // _header_kv.insert(std::make_pair("Content-Type", _content_type));

        _response_headers.push_back("Content-Length" + header_sep + std::to_string(_content_length) + http_line_sep);
        _response_headers.push_back("Content-Type" + header_sep + _content_type + http_line_sep);
    }

public:
    Response(const std::string &path)
        : _http_version("HTTP/1.0"),
          _status_code(200),
          _status_code_discribtion("OK"),
          _path(path),
          _block_line("\r\n")
    {
    }
    void Serialize(std::string &responseMassage)
    {
        getStatusLine();
        _content_type = "text/html"; // 暂定
        getResponseHeader();
        getResponseText();

        //开始序列化
        std::string header_string;
        for (auto &header : _response_headers)
            header_string = header_string + header;

        responseMassage = _status_line + 
                          header_string + _block_line +
                          _response_text;
    }

private:
    /*-------------------请求的详细信息------------------*/
    // 状态行详细信息
    std::string _http_version;            // http版本
    int _status_code;                     // 状态码
    std::string _status_code_discribtion; // 状态码描述
    // 响应报头详细信息
    // std::unordered_map<std::string, std::string> _header_kv; // 请求报头的K_V内容
    std::string _path;         // 响应文件的路径
    int _content_length;       // 正文长度
    std::string _content_type; // 正文属性
    /*----------------------------------------------------*/

    /*----------------HTTP请求格式----------------------*/
    std::string _status_line;                   // 状态行
    std::vector<std::string> _response_headers; // 响应报头
    std::string _block_line;                    // 空行
    std::string _response_text;                 // 响应正文
    /*----------------------------------------------------*/
};

class HttpServer
{
public:
    std::string httpResponse(std::string requestMassage, InetAddr clientAddr)
    {
        //std::cout << "---------------------------------------" << std::endl;
        //std::cout << requestMassage;
        //std::cout << "-----------------Print----------------------" << std::endl;

        Request request;
        request.Deserialize(requestMassage); // 反序列化请求信息
         //request.Print();

        std::string responseMassage;
        std::string path = request.getPath(int());
        Response response(path);
        response.Serialize(responseMassage);

        LOG(INFO, "[%s:%d] request %s......", clientAddr.IP().c_str(), clientAddr.Port(), path.c_str());

        //std::cout << responseMassage << std::endl;
    
        return responseMassage;
    }
};